

#ifndef BPDC_H
#define	BPDC_H
#include <selforg/matrix.h>
#include <stdlib.h>
#include <cmath>
#include <vector>
using namespace matrix; 

/** 
 * File:   bpdc.h
 * 
 * Class that implements the Back-propagation Decorellation learning rule (BPDC) in 
 * Recurrent Neural Networks as presented in section 3.1.2 of the thesis.
 * 
 * BPDC is based on the decorrelation of networks' nodes value and the backpropagation
 *  of the errors occured in the last two time steps
 * 
 * @author:  Athanasios Polydoros
 * @version: 1.0
 * Created on 01 July 2013, 15:17
 */
class BPDC {
public:
     /**
     * Class constructor that initialise the members of class. Has to be called
     * in the controller's init method.
     * 
     * @param num_Sensors The number of robot sensors, used as network's outputs
     * @param num_Motors  The number of motors, used as inputs
     */
    BPDC(int numSensors, int numMotors);
     
    /**
     * Class destructor
     */
    virtual ~BPDC();
    
     /**
     * Set the current inputs of the network
     * 
     * @param motors The values of robot's motors   
     */
    void setState(Matrix motors);
    
    /**
     * Sets the desired output of the network. This method is called in 
     * controler's method : learn
     * 
     * @param fut_sensor the robot's sensory values 
     */
    void setDesiredOut(Matrix futureSensor);
    
     /**
    *  Predicts the future sensor values based on the current motor commands (inputs).
     * 
     * 
     * @return Matrix that contains the predicted sensory values. 
    */
    Matrix predict();
    
    /**
      * Calculate the jacobian matrix of the network.
      * The derivative of outputs wrt inputs.
      * Should be called after activation of network
      * 
      * @param the input nodes values 
      * @return MxM Jacobian matrix
      */
    Matrix getModelMatrix ( Matrix input);
    
      double dt;         /**< time frame, dt=1 for discrete time*/
      double heta;      /**< Learning rate*/
      double epsillon;  /**< regularization term (0.001)*/
private:
     
    /**
     *  Calculate the network's activations
     * 
     * @return Matrix with the values of each node activation
     */
    Matrix simulateNet(); 
    
    
    /**
     *Update weights based on BPDC learning rule.
     * 
     */ 
  void updateWeights();
     
     /**
     *The squashing function of the network. the hyperbolic
     * tangent used (tanh)
     * 
     * @param node the value that will be mapped
     */
    static double squash(double node);
    
    /**
     *The derivative of squashing function of the network
     * 
     * @param node the value that will be mapped
     */
    static double squash_derivative(double node);
     
    /**
     *Method that implements the Kronnecker delta 
     * @return 1 if i=0 , otherwise 0
     */
    int kronneckerDelta (int i, int k);
    
     std::vector <Matrix> desiredSens; /**< History of the last two desired outputs*/
    std::vector<Matrix> errorBuff; /**< History of the last two errors*/
    Matrix weights; /**< Matrix containing the weights ofthe network*/
    Matrix nodes; /**< The values of nodes before activation of the network*/
    Matrix inputWeights; /**< Matrix with the values of weights that connect the input with the reservoir*/
    Matrix inputNodes; /**< The values of input nodes*/
    int inputNum; /**< The number of input nodes*/
    int outputNum; /**< The number of output nodes*/
    int reservoirNum; /**< The number of reservoir nodes*/
    
};

#endif	/* BPDC_H */

